package com.yunchao.library.socket

import com.yunchao.library.socket.logger.SocketLogger
import com.yunchao.library.socket.model.card.CommandData
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.channels.BufferOverflow
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.json.JSONArray
import org.json.JSONObject
import java.net.ServerSocket
import java.net.Socket


object CommandReceiver {
    private val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())
    private var serverSocket: ServerSocket? = null
    private var serverJob: Job? = null

    // 使用密封类表示结果
    sealed class CommandResult {
        data class Success(val command: CommandData) : CommandResult()
        data class Error(val exception: Throwable, val rawData: String? = null) : CommandResult()
        object ConnectionClosed : CommandResult()
    }

    // 使用背压策略处理高负载情况
    private val _commandFlow = MutableSharedFlow<CommandResult>(
        extraBufferCapacity = 64,
        onBufferOverflow = BufferOverflow.DROP_OLDEST
    )
    val commandFlow: SharedFlow<CommandResult> = _commandFlow.asSharedFlow()


    fun start(port: Int) {
        require(port in 1..65535) { "Invalid port number: $port" }

        if (serverJob?.isActive == true) {
            SocketLogger.logWarning("刷卡服务已经在运行中")
            return
        }

        serverJob = scope.launch {
            try {
                ServerSocket(port).also { serverSocket = it }.use { socket ->
                    SocketLogger.logOperation("启动刷卡服务: IP = ${socket.inetAddress}, PORT = ${socket.localPort}")
                    while (isActive) {
                        try {
                            socket.accept().use { clientSocket ->
                                handleClient(clientSocket)
                            }
                        } catch (e: Exception) {
                            if (isActive) {
                                _commandFlow.emit(CommandResult.Error(e))
                                SocketLogger.logError("处理客户端连接时出错: ${e.message}")
                                delay(1000) // 防止错误循环过快
                            }
                        }
                    }
                }
            } catch (e: Exception) {
                if (isActive) {
                    _commandFlow.emit(CommandResult.Error(e))
                    SocketLogger.logError("启动服务时出错: ${e.message}")
                }
            } finally {
                serverSocket = null
                _commandFlow.emit(CommandResult.ConnectionClosed)
            }
        }
    }

    fun stop() {
        SocketLogger.logOperation("关闭刷卡服务")
        serverJob?.cancel()
        try {
            serverSocket?.close()
        } catch (e: Exception) {
            SocketLogger.logError("关闭ServerSocket时出错: ${e.message}")
        }
    }

    private suspend fun handleClient(socket: Socket) = withContext(Dispatchers.IO) {
        try {
            socket.getInputStream().bufferedReader().use { reader ->
                val rawResponse = reader.readLine()?.trim() ?: run {
                    SocketLogger.logWarning("接收到空数据")
                    return@use
                }

                SocketLogger.logOperation("收到刷卡数据: $rawResponse")

                when (val result = parseRawResponse(rawResponse)) {
                    is CommandResult.Success -> _commandFlow.emit(result)
                    is CommandResult.Error -> {
                        _commandFlow.emit(result.copy(rawData = rawResponse))
                        SocketLogger.logError("解析数据出错: ${result.exception.message}")
                    }

                    else -> Unit
                }
            }
        } catch (e: Exception) {
            _commandFlow.emit(CommandResult.Error(e))
            SocketLogger.logError("处理客户端数据时出错: ${e.message}")
        }
    }

    private fun parseRawResponse(rawResponse: String): CommandResult {
        return try {
            val jsonString = extractJsonFromMixedResponse(rawResponse)
                ?: return CommandResult.Error(
                    IllegalArgumentException("Invalid JSON format"),
                    rawResponse
                )

            CommandResult.Success(parseJsonToCommandData(jsonString))
        } catch (e: Exception) {
            CommandResult.Error(e, rawResponse)
        }
    }

    private fun extractJsonFromMixedResponse(rawResponse: String): String? {
        // 使用正则表达式更可靠地提取JSON
        val jsonRegex = """\{[^{}]*\}""".toRegex()
        return jsonRegex.find(rawResponse)?.value?.takeIf {
            runCatching { JSONObject(it) }.isSuccess
        }
    }

    private fun parseJsonToCommandData(jsonString: String): CommandData {
        val jsonObject = JSONObject(jsonString)

        return CommandData(
            dwCommand = jsonObject.safeGetInt("dwCommand"),
            dwTimeOut = jsonObject.safeGetInt("dwTimeOut"),
            wDeviceID = jsonObject.safeGetInt("wDeviceID"),
            wType = jsonObject.safeGetInt("wType"),
            wVersion = jsonObject.safeGetInt("wVersion"),
            lpData = parseLpData(jsonObject.optJSONObject("lpData"))
        )
    }

    private fun parseLpData(lpDataObj: JSONObject?): CommandData.LpData {
        val dataObj = lpDataObj ?: JSONObject()

        return CommandData.LpData(
            RequestID = dataObj.safeGetInt("RequestID"),
            dwCommandCode = dataObj.safeGetInt("dwCommandCode"),
            dwEventID = dataObj.safeGetInt("dwEventID"),
            hResult = dataObj.safeGetInt("hResult"),
            hService = dataObj.safeGetInt("hService"),
            lpBuffer = parseLpBufferArray(dataObj.optJSONArray("lpBuffer")),
            tsTimestamp = parseTimestamp(dataObj.optJSONObject("tsTimestamp"))
        )
    }

    private fun parseLpBufferArray(array: JSONArray?): List<CommandData.LpData.LpBuffer> {
        return array?.let {
            (0 until it.length()).mapNotNull { i ->
                it.optJSONObject(i)?.let { obj ->
                    CommandData.LpData.LpBuffer(
                        fwWriteMethod = obj.safeGetInt("fwWriteMethod"),
                        lpbData = obj.safeGetString("lpbData"),
                        ulDataLength = obj.safeGetInt("ulDataLength"),
                        wDataSource = obj.safeGetInt("wDataSource"),
                        wStatus = obj.safeGetInt("wStatus")
                    )
                }
            }
        } ?: emptyList()
    }

    private fun parseTimestamp(tsObj: JSONObject?): CommandData.LpData.TsTimestamp {
        val obj = tsObj ?: JSONObject()
        return CommandData.LpData.TsTimestamp(
            wDay = obj.safeGetInt("wDay"),
            wYear = obj.safeGetInt("wYear"),
            wHour = obj.safeGetInt("wHour"),
            wMonth = obj.safeGetInt("wMonth"),
            wDayOfWeek = obj.safeGetInt("wDayOfWeek"),
            wMinute = obj.safeGetInt("wMinute"),
            wMilliseconds = obj.safeGetInt("wMilliseconds"),
            wSecond = obj.safeGetInt("wSecond")
        )
    }

    // JSON安全访问扩展函数
    private fun JSONObject.safeGetInt(key: String, default: Int = 0): Int {
        return try {
            optInt(key, default)
        } catch (e: Exception) {
            SocketLogger.logError("解析字段 $key 出错: ${e.message}")
            default
        }
    }

    private fun JSONObject.safeGetString(key: String, default: String = ""): String {
        return try {
            optString(key, default)
        } catch (e: Exception) {
            SocketLogger.logError("解析字段 $key 出错: ${e.message}")
            default
        }
    }
}